package com.cf.service.impl;

import com.cf.Constant;
import com.cf.service.HttpService;
import com.cf.service.ThirdPartException;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
public class HttpServiceImpl implements HttpService {

    @Autowired
    private HttpServiceProperties httpServiceProperties;

    private RequestConfig requestConfig = null;

    private PoolingHttpClientConnectionManager cm = null;

    @PostConstruct
    public void init() {
        requestConfig = RequestConfig.custom().setSocketTimeout(httpServiceProperties.getSocketTimeout()).setConnectTimeout(httpServiceProperties.getConnectTimeout()).setConnectionRequestTimeout(httpServiceProperties.getConnectionRequestTimeout()).build();
        LayeredConnectionSocketFactory sslsf = getSSLSocketFactory();
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build();
        cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        cm.setMaxTotal(200);
        cm.setDefaultMaxPerRoute(20);
    }

    private LayeredConnectionSocketFactory getSSLSocketFactory() {
        LayeredConnectionSocketFactory sslsf = null;
        try {
            sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return sslsf;
    }

    private CloseableHttpClient getHttpClient() {
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
        return httpClient;
    }


    @Override
    public String get(String s) throws ThirdPartException {
        CloseableHttpClient httpClient = getHttpClient();

        HttpGet get = new HttpGet(s);
        get.setConfig(requestConfig);
        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(get);
            HttpEntity entity = httpResponse.getEntity();
            if (null != entity) {
                HttpEntity httpResponseEntity = httpResponse.getEntity();
                return EntityUtils.toString(httpResponseEntity, "utf-8");
            } else {
                return null;
            }
        } catch (Exception e) {
            throw new ThirdPartException(Constant.ERROR.getCode(), "http请求失败！", e);
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Override
    public String post(String s, Map<String, Object> parameter, boolean ignoreNull) throws ThirdPartException {
        CloseableHttpClient httpClient = getHttpClient();
        HttpPost post = new HttpPost(s);
        post.setConfig(requestConfig);
        CloseableHttpResponse httpResponse = null;
        try {

            List<NameValuePair> list = new ArrayList<NameValuePair>();
            if (parameter != null) {
                Iterator iterator = parameter.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Object> elem = (Map.Entry<String, Object>) iterator.next();
                    if (elem.getValue() == null) {
                        if (ignoreNull) {
                            continue;
                        }
                    }
                    list.add(new BasicNameValuePair(elem.getKey(), elem.getValue().toString()));
                }
            }
            if (list.size() > 0) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "utf-8");
                post.setEntity(entity);
            }

            httpResponse = httpClient.execute(post);
            HttpEntity resEntity = httpResponse.getEntity();
            if (resEntity != null) {
                return EntityUtils.toString(resEntity, "utf-8");
            } else {
                return null;
            }
        } catch (Exception e) {
            throw new ThirdPartException(Constant.ERROR.getCode(), "http请求失败！", e);
        } finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
